home *** CD-ROM | disk | FTP | other *** search
/ Macwelt 1 / Macwelt DVD 1.toast / Web-Publishing / HTML-Editoren / Alpha ƒ / Tcl / Modes / Matlab mode / matlabEngine.tcl < prev    next >
Encoding:
Text File  |  2000-05-10  |  8.2 KB  |  306 lines

  1. ################################################################################
  2. #
  3. # matlabEngine.tcl, part of the matlab mode package
  4. # Make editing MATLAB files more fun
  5. ################################################################################
  6.  
  7. proc matlabEngine.tcl {} {}
  8.  
  9. ################################################################################
  10. #  Carriage return proc for edit, command, and history windows.
  11. ################################################################################
  12.  
  13. proc bind::MATLcarriageReturn {} {
  14.     global MATLmodeVars
  15.  
  16.     if {[matlabIsShell]} {
  17.         matlabDoShellLine
  18.     } elseif {[matlabIsHist]} {
  19.         matlabAddCommandHistory [matlabDoSelectionOrLine]
  20.         bringToFront $MATLmodeVars(CmdHistWinName)
  21.     } else {
  22.         if { [isSelection] } { deleteSelection }
  23.         if [text::isInComment [getPos] start] {
  24.             insertText "\r${start}"
  25.             return
  26.         }
  27.         
  28.         insertText "\r"
  29.         
  30.         if {$MATLmodeVars(elecReturn)} {
  31.             previousLine
  32.             MATL::indentLine
  33.             goto [nextLineStart [getPos]]
  34.             MATL::indentLine
  35.         }            
  36.     }
  37. }
  38.  
  39. ################################################################################
  40. #  Arrow key replacement
  41. ################################################################################
  42.  
  43. proc matlabUp {} {
  44.     if {[matlabIsShell]} {
  45.         matlabPrevCommand
  46.     } elseif {[matlabIsHist]} {
  47.         upBrowse
  48.     } else {
  49.         previousLine
  50.     }
  51. }
  52.  
  53. proc matlabDown {} {
  54.     if {[matlabIsShell]} {
  55.         matlabNextCommand
  56.     } elseif {[matlabIsHist]} {
  57.         downBrowse
  58.     } else {
  59.         nextLine
  60.     }
  61. }
  62.  
  63.  
  64. #################################################################################
  65. #  cmd-double clicking, edit or get help on command
  66. ################################################################################
  67.  
  68. proc MATL::DblClick {from to shift option control} {    
  69.     global MATLmodeVars
  70.     
  71.     set DblClickEdits [expr !$control == $MATLmodeVars(DblClickEdits)]
  72.  
  73.     # Force command names to lower case.
  74.     # (Mac filenames are case-insensitive, anyway)
  75.     set text [string tolower [getText $from $to]]
  76.     
  77.     if {! $DblClickEdits} {
  78.         getMatlabHelp $text
  79.     } else {
  80.         MATL::editMfile $text
  81.     }
  82. }
  83.  
  84.  
  85. ################################################################################
  86. #  Auto-indentation
  87. #        1. Identify previous line ignoring comments
  88. #        2.    Find leading whitespace for previous line
  89. #        3.    Increase whitespace if previous line starts a block
  90. #        4.    Decrease whitespace if current line ends a block
  91. #     5. Eliminate whitespace if current line starts a procedure
  92. ################################################################################
  93.  
  94. proc MATL::indentLine {} {
  95.     
  96.     # Comment Pattern
  97.     set comPat {^[ \t]*%([^\r\n]*)}
  98.     
  99.     # Begining of block pattern
  100.     set bobPat {^[ \t]*(if|else|elseif|for|switch|case|while|otherwise)[ \t\r\n;,%]}
  101.     
  102.     # End of block pattern
  103.     set eobPat {^[ \t]*(end|else|elseif|case|otherwise)[ \t\r\n;,%]}
  104.     
  105.     # Begining and end of block pattern
  106.     set baeobPat {^[ \t]*(if|else|elseif|for|case|otherwise)[^%]*[ \t]+(end)[ \t\r\n;,%]}
  107.     
  108.     # Function Line Pattern
  109.     set funPat {^[ \t]*(function)[ \t]+([[]*[^][\n\r]+[]]*[ \t]*=[ \t]*)*([a-z0-9_]+)[ \t]*([(]+[^)(\n\r]+[)]+)*}
  110.     
  111.     # Get line to indent
  112.     set beg [lineStart [getPos]]
  113.     set text [getText $beg [nextLineStart $beg]]
  114.     regexp -- {^[ \t]*} $text white
  115.     set len [string length $white]
  116.         
  117.     # Init some vars
  118.     set begCmt $beg
  119.     set prvPos $beg
  120.     set endCmt $beg
  121.     set prvPos $beg
  122.     
  123.     # Find last previous non-comment line and get its leading whitespace
  124.         
  125.     while {[pos::compare $begCmt <= $prvPos] && [pos::compare $endCmt >= $prvPos]} {
  126.     
  127.     # Find the last non-blank line that precedes the comment block
  128.     if {![catch {search -f 0 -r 1 -s -i 0 -m 0 {^[ \t]*[^ \t\r]} [pos::math $begCmt -1]} lst]} {    
  129.             
  130.         set prvPos [lindex $lst 0]
  131.         set line [getText [lindex $lst 0] [nextLineStart [lindex $lst 0]]]
  132.         set lwhite [getText [lindex $lst 0] [pos::math [lindex $lst 1] - 1]]
  133.             
  134.         # Find the next preceding comment block
  135.         if {![catch {search -f 0 -r 1 -s -i 0 -m 0 $comPat $prvPos} lstCmt]} {
  136.         set begCmt [lindex $lstCmt 0]
  137.         set endCmt [lindex $lstCmt 1]
  138.         } else {
  139.         break
  140.         }
  141.             
  142.     } else {
  143.         # Handle search failure at top-of-file
  144.         if {[pos::compare $beg !=  [minPos]]} {
  145.         set line [getText [minPos] [nextLineStart [minPos]]]
  146.         } else {
  147.         set line "%\r"
  148.         }
  149.         set lwhite ""
  150.         break
  151.     }
  152.     }
  153.     
  154.     # If the preceeding line begins a block increase the whitespace
  155.     if {[regexp -nocase -- $bobPat $line]} {
  156.     # but not if it also ended the block
  157.     if {![regexp -nocase -- $baeobPat $line]} {
  158.         append lwhite "\t"
  159.     }
  160.     }
  161.  
  162.     # If the current line ends a block decrease the whitespace
  163.     if {[regexp -nocase -- $eobPat $text]} {
  164.     set lwhite [string range $lwhite 0 [expr [string length $lwhite] - 2]]
  165.     }
  166.     
  167.     # If the current line starts a new function use no whitespace
  168.     if {[regexp -nocase -- $funPat $text allofit subType subVars subName]} {
  169.     set lwhite ""
  170.     }
  171.  
  172.     # Put in the white space
  173.     if {$white != $lwhite} {
  174.     replaceText $beg [pos::math $beg + $len] $lwhite
  175.     }
  176.     goto [pos::math $beg + [string length $lwhite]]
  177. }
  178.  
  179.  
  180. ################################################################################
  181. #  Electric Semicolon
  182. ################################################################################
  183.  
  184. proc MATL::electricSemi {} {
  185.  
  186.     set pos [getPos]
  187.     set start [lineStart $pos]
  188.     set text [getText $start $pos]
  189.     
  190.     # Check if we are in a string or an array
  191.     if {[string first {'} $text] != -1 || [string first {[} $text] != -1} {
  192.     set quotes 0
  193.     set lefts 0
  194.     set rights 0
  195.     set len [string length $text]
  196.     for {set i 0} {$i < $len} {incr i} {
  197.         switch  -- [string index "$text" $i] {
  198.         \[    { incr lefts }
  199.         \]    { incr rights }
  200.         \'    { incr quotes }
  201.         }
  202.     }
  203.     if {[expr $quotes % 2]} {
  204.         insertText ";"
  205.         return
  206.     } elseif    {$lefts != $rights} {
  207.         insertText ";"
  208.         return
  209.     }
  210.     }
  211.     
  212.     insertText ";"
  213.     bind::MATLcarriageReturn
  214. }
  215.  
  216.  
  217. ################################################################################
  218. #  Electric Semicolon Jump
  219. #  Use with templates on last line of a block
  220. ################################################################################
  221.  
  222. proc MATL::electricSemiJump {} {
  223.     insertText ";"
  224.     ring::+
  225. }
  226.  
  227. ################################################################################
  228. #  Set the named marks
  229. ################################################################################
  230.  
  231. proc MATL::MarkFile {} {
  232.     global MATLmodeVars
  233.     set pos [minPos]
  234.     
  235.     set funPat {^[ \t]*(function)[ \t]+([[]*[^][\n\r]+[]]*[ \t]*=[ \t]*)*([a-z0-9_]+)[ \t]*([(]+[^)(\n\r]+[)]+)*}
  236.     
  237.     while {![catch {search -s -f 1 -r 1 -m 0 -i 0 $funPat $pos} res]} {
  238.     set start [lindex $res 0]
  239.     set end [pos::math [lindex $res 1] + 1]
  240.     set text [getText $start $end]
  241.     if {[regexp -nocase -- $funPat $text allofit subType subVars subName]} {
  242.         set locs($subName) [lineStart $start]
  243.     }
  244.     set pos $end
  245.     }
  246.     
  247.     if {[info exists locs]} {
  248.     foreach f [lsort -ignore [array names locs]] {
  249.         setNamedMark $f $locs($f) $locs($f) $locs($f)
  250.     }
  251.     }
  252. }
  253.  
  254. ################################################################################
  255. #  Edit an m-file if available, else get help if built-in
  256. ################################################################################
  257.  
  258. proc MATL::editMfile {fileName} {
  259.     
  260.     set varPat {is a (.+)}
  261.     set pathPat {(.*):([^:]*)}
  262.     
  263.     set res [matlabWhichFile $fileName]
  264.     if {$res == ""} {return}
  265.  
  266.     # If variable or built-in function, get help info.
  267.     if {[regexp -- $varPat $res type]} {
  268.         getMatlabHelp $fileName
  269.         
  270.     # If it's an m-file open it.
  271.     } elseif {[regexp -- $pathPat $res dir fname]} {
  272.         if {[catch {edit -c $res}]} {
  273.             beep
  274.             alertnote "Could not open m-file \"$res\""
  275.         } else {
  276.             icon -o
  277.         }
  278.         
  279.     # If MATLAB doesn't recognize it, check if it's an
  280.     # m-file in the same folder as the current script
  281.     # If not, just display MATLAB's original response.
  282.     } else {
  283.         set path [absolutePath :${fileName}.m] 
  284.         if [file exists $path] {
  285.             if {[catch "edit -c \"$path\""]} {
  286.                 beep
  287.                 alertnote "Could not open m-file \"$res\""
  288.             } else {
  289.                 icon -o
  290.             }
  291.         } else {
  292.             # Now it could be a contents.m
  293.             set resC [matlabWhichFile "$fileName:contents.m"]
  294.             if {$resC == ""} {return}
  295.             if {[catch {edit -c $resC}]} {
  296.                 beep
  297.                 alertnote "Could not open m-file \"$res\""
  298.             } else {
  299.                 icon -o
  300.             }
  301.        }
  302.     }
  303. }
  304.